#include "LCommon.h"

void ClientListener::Loop()
{
	int rc = 0;
	WSAData wsd;
	rc = WSAStartup(MAKEWORD(2, 0), &wsd);
	if(rc == SOCKET_ERROR)
	{
		Log->Notice("ClientListener", "Could not start Winsock!\n");
		return;
	}
	m_listensocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if(m_listensocket == SOCKET_ERROR)
	{
		Log->Notice("ClientListener", "Could not create listensocket!\n");
		return;
	}
	SOCKADDR_IN sin;
	memset(&sin, NULL, sizeof(SOCKADDR_IN));
	sin.sin_port = htons(logon_config->GetUInt("Network Settings", "ListenPort", 3724));
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_family = AF_INET;
	rc = bind(m_listensocket, (const sockaddr*)&sin, sizeof(SOCKADDR_IN));
	if(rc == SOCKET_ERROR)
	{
		Log->Notice("ClientListener", "Bind unsuccessfull on port 3724!\n");
		return;
	}
	rc = listen(m_listensocket, 10);
	if(rc == SOCKET_ERROR)
	{
		Log->Notice("ClientListener", "Could not listen on port 3724!\n");
		return;
	}
	Log->Success("ClientListener", "Waiting for new clients on port '%u'", ntohs(sin.sin_port));
	while(ThreadState)
	{
		FD_ZERO(&m_readset);
		FD_SET(m_listensocket, &m_readset);
		if(m_clients.size())
		{
			vector<AuthSocket*>::iterator itr = m_clients.begin();
			vector<AuthSocket*>::iterator end = m_clients.end();
			for( ; itr != end; ++itr)
				FD_SET((*itr)->m_socket, &m_readset);
		}
		select(0, &m_readset, NULL, NULL, NULL);
		if(FD_ISSET(m_listensocket, &m_readset))
		{
			AuthSocket* auth = new AuthSocket();
			auth->ThreadState = 1;
			ThreadPool.ExecuteTask(auth);
			SOCKADDR_IN sin;
			int len = sizeof(SOCKADDR_IN);
			auth->m_socket = WSAAccept(m_listensocket, (sockaddr*)&sin, &len, NULL, 0);
			Log->Notice("ClientListener", "Got new Client from '%s'", inet_ntoa(sin.sin_addr));
			m_clients.push_back(auth);
		}
		if(m_clients.size())
		{
			vector<AuthSocket*>::iterator itr = m_clients.begin();
			vector<AuthSocket*>::iterator end = m_clients.end();
			for( ; itr != end; ++itr)
			{
				if(FD_ISSET((*itr)->m_socket, &m_readset))
				{
					char buffer[65535];
					int x = recv((*itr)->m_socket, buffer, 65535, 0);
					if(x == SOCKET_ERROR || x == 0)
					{
						AuthSocket* sk = (*itr);
						m_clients.erase(itr);
						sk->Remove();
						end = m_clients.end();
						delete sk;
						if(itr == end)
							break;
					}
					if(x < 4)
					{
						continue;
					}
					RealmPacket* pk = new RealmPacket();
					pk->Resize(x);
					memcpy(pk->Contents(), buffer, x);
					ui8 opcode = *buffer;
					(*itr)->m_readlock.Acquire();
					(*itr)->m_readbuffer.insert(pk);
					(*itr)->m_readlock.Release();
				}
			}
		}
	}
}